
const { ccclass, property } = cc._decorator;

@ccclass
export default class Rolling extends cc.Component {
    /**当前数字 */
    private m_curNum: number = 0;
    /**字体高度 */
    private m_fontHeight: number = 0;
    /**开始位置 */
    private m_startPoint: cc.Vec2 = cc.v2(0, 0);
    /**单个个数 */
    private m_singleNum: number = 0;
    /**双个个数 */
    private m_doubleNum: number = 0;
    private m_isRollIng: boolean = false;

    /**轮训次数 */
    private m_rollCounts: number = 0;
    /**滚动速度 */
    private m_rollSpeed: number = 300;

    private roolNode: cc.Node = null;

    onLoad() {
        this.roolNode = this.node;
    }

    start() {
        this.roolNode.x = this.m_startPoint.x;
        this.roolNode.y = this.m_startPoint.y;
        this.m_singleNum = this.roolNode.childrenCount / 2;
        this.m_doubleNum = this.roolNode.childrenCount;
        this.m_fontHeight = this.roolNode.height / this.roolNode.childrenCount;
    }

    public initValue(num: number) {
        this.m_curNum = num;
        this.roolNode.y = num * this.m_fontHeight;
    }

    public setParam(rollCount: number, rollSpeed: number) {
        this.m_rollCounts = rollCount;
        this.m_rollSpeed = rollSpeed
    }

    public async rollToValue(num: number) {
        let tempNum: number = num;
        if (this.m_isRollIng) { return };
        if (tempNum < 0 || tempNum > this.m_singleNum) { return };
        this.m_isRollIng = true;
        if (num < this.m_curNum) {
            num += 10;
        }
        //到目标值长度和单次轮训长度
        let distance1: number = (num - this.m_curNum) * this.m_fontHeight;
        let distance2: number = this.m_singleNum * this.m_fontHeight;
        let time: number;
        if (this.m_rollCounts > 0) {
            time = await this.rollAccelerateAction(distance2) as number;
            time = await this.rollUniformityAction(distance2, time) as number;
            time = await this.rollDecelerateAction(distance1, num, tempNum) as number;
            this.m_isRollIng = false;
            console.log('-----执行完毕----');
        }
        else {
            if (tempNum == this.m_curNum) { return };
            time = distance1 / this.m_rollSpeed;
            cc.tween(this.roolNode)
                .by(time, { position: new cc.Vec3(0, distance1, 0) }, { easing: 'quartInOut' })
                .call(() => {
                    this.initValue(tempNum);
                    this.m_isRollIng = false;
                })
                .start();
        }
    }

    /**加速阶段 */
    private rollAccelerateAction(distance: number) {
        let array: number[] = [];
        let time: number = distance / this.m_rollSpeed;
        return new Promise((resolve, reject) => {
            cc.tween(this.roolNode)
                .by(time, { position: new cc.Vec3(0, distance, 0), }, {
                    easing: 'quartIn',
                    onUpdate: (target: cc.Vec3, ratio: number) => {
                        array.push(target.y);
                    }
                })
                .call(() => {
                    this.initValue(this.m_curNum);
                    let value = array[array.length - 1] - array[array.length - 2];
                    let speed = value / (1 / array.length);
                    resolve(distance / speed);
                })
                .start();
        });
    }

    /**匀速阶段 */
    private rollUniformityAction(distance: number, time: number) {
        let count: number = 0;
        return new Promise((resolve, reject) => {
            cc.tween(this.roolNode)
                .by(time, { position: new cc.Vec3(0, distance, 0), })
                .call(() => {
                    this.initValue(this.m_curNum);
                    count++;
                }).union().repeat(this.m_rollCounts)
                .call(() => {
                    resolve(null);
                    console.log(count);
                })
                .start();
        });
    }

    /**减速阶段 */
    private rollDecelerateAction(distance: number, num: number, tempNum: number) {
        let time: number = distance / this.m_rollSpeed;
        return new Promise((resolve, reject) => {
            cc.tween(this.roolNode)
                .by(time, { position: new cc.Vec3(0, distance, 0) }, {
                    easing: 'quartOut'
                })
                .call(() => {
                    this.initValue(tempNum);
                    resolve(null);
                })
                .start();
        });
    }
}


